package com.kly.user.task.v2;

import cn.hutool.core.net.NetUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.HttpUtil;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.api.client.util.Joiner;
import com.google.api.client.util.Lists;
import com.google.common.collect.Maps;
import com.google.common.eventbus.AsyncEventBus;
import com.kly.enums.ParameterTypeEnum;
import com.kly.user.chatterService.ChatService;
import com.kly.user.db.dao.*;
import com.kly.user.db.dbo.UserWlmDBO;
import com.kly.user.db.entity.UserGreetingCommonContentEntity;
import com.kly.user.db.entity.UserGreetingContentEntity;
import com.kly.user.db.entity.UserGreetingSendLogEntity;
import com.kly.user.db.entity.UserSendMsgDetailEntity;
import com.kly.user.dto.chatter.request.ConversationReq;
import com.kly.user.enums.AppCodeEnum;
import com.kly.user.enums.AppEnum;
import com.kly.user.enums.OnlineStatus;
import com.kly.user.eventbus.ActionEnum;
import com.kly.user.eventbus.Event;
import org.apache.logging.log4j.util.Strings;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SendFlashChatMsgTask {

    private static Log logger = LogFactory.getLog(SendFlashChatMsgTask.class);

    @Resource
    UserWlmDao userWlmDao;
    @NacosValue(value = "${send.flashchat.times:10}", autoRefreshed = true)
    private Integer sendFlashChatTimes;
    @NacosValue(value = "${send.flashchat.max.times:300}", autoRefreshed = true)
    private Integer sendFlashChatMaxTimes;
    @NacosValue(value = "${send.flashchat.url:http://localhost:9104/api/im/message/sendMsg}", autoRefreshed = true)
    private String sendFlashchatUrl;
    @Resource
    UserGreetingContentDao userGreetingContentDao;
    @Resource
    UserGreetingCommonContentDao userGreetingCommonContentDao;
//    @NacosValue(value = "${task.job.executor.ip}", autoRefreshed = true)
    @NacosValue(value = "${master.task.job.executor.ip}", autoRefreshed = true)
    private String taskJobExecutor;
    @NacosValue(value = "${enable.flashchat.switch:false}", autoRefreshed = true)
    private Boolean enableFlashChatSwitch;
    @Resource
    AsyncEventBus pushEventBus;
    @Resource
    ChatService chatService;
    @Resource
    UserMsgUnreadNumDao userMsgUnreadNumDao;
    @Resource
    UserGreetingSendLogDao userGreetingSendLogDao;
    @Resource
    UserSendMsgDetailDao userSendMsgDetailDao;
    private final static String taskName = "建联系统自动任务";
    @NacosValue(value = "${retry.send.msg.times.limit:10}", autoRefreshed = true)
    private Integer retrySendMsgTimesLimit;


    private String localIP = NetUtil.getLocalhostStr();


    @Scheduled(fixedDelay = 1000 * 20)
    public void run() {
        logger.info("SendFlashChatMsgTaskStart");

        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============NotTaskJobExecutor, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!enableFlashChatSwitch) {
            logger.info("=============NotTaskJobExecutor, enableFlashchatSwitch:{}", enableFlashChatSwitch);
            return;
        }

        List<UserWlmDBO> userWlmDBOs = userWlmDao.needSendFlashMsgList(100);
        logger.info("SendFlashChatMsgTask === 待发送记录条数：{}", userWlmDBOs.size());

        if (CollectionUtils.isEmpty(userWlmDBOs)) {
            return;
        }

        for (UserWlmDBO o : userWlmDBOs) {
            if (o.getTimes() != null && o.getTimes() > sendFlashChatTimes) {
                final JSONObject params = new JSONObject();
                JSONObject resultJson = null;
                try {
                    String allCommonGreetings = getCommonGreeting();
                    final String sendMsg = getUserGreetingContentEntities(o.getUserCode(), allCommonGreetings);
                    if (StringUtils.isEmpty(sendMsg)) {
                        logger.info("SendFlashChatMsgTask === 无消息记录：{}", JSONObject.toJSONString(userWlmDBOs));
                        continue;
                    }

                    params.put("fromUserCode", o.getUserCode());
                    params.put("toUserCode", o.getUserCodeWlm());
                    params.put("content", sendMsg);
                    params.put("source", "SendFlashChatMsgTask");

                    final HashMap<String, String> header = Maps.newHashMap();
                    header.put("accept", "application/json");
                    header.put("content-type", "application/json");

                    final long startTime = System.currentTimeMillis();
                    logger.info("===SendFlashChatMsgTask, fromUserCode:{}, toUserCode:{},msg:{}", o.getUserCode(), o.getUserCodeWlm(), sendMsg);
                    final String result = HttpUtil.postPageBody(sendFlashchatUrl, header, params.toJSONString());


                    if (StringUtils.isEmpty(result)) {
                        logger.error("===SendFlashChatMsgTask, fromUserCode:{}, toUserCode:{},times:{}, reusltIsNull", o.getUserCode(), o.getUserCodeWlm(), o.getTimes());
                        continue;
                    }

                    resultJson = JSONObject.parseObject(result);
                    final int code = resultJson.getIntValue("code");
                    if (code != 0) {
                        logger.error("===SendFlashChatMsgTask, fromUserCode:{}, toUserCode:{},times:{}, reuslt:{}", o.getUserCode(), o.getUserCodeWlm(), o.getTimes(), result);
                        executeFailed(params.toJSONString(), resultJson.toJSONString());
                        continue;
                    }

                    // 添加未读会话数
                    userMsgUnreadNumDao.saveUnReadMsgNum(o.getUserCode(), o.getUserCodeWlm(), SecureUtil.md5(o.getUserCodeWlm() + o.getUserCode()), null);
                    logger.info("===SendFlashChatMsgTask, fromUserCode:{}, toUserCode:{},times:{}, reuslt: {}, costTime:{}", o.getUserCode(), o.getUserCodeWlm(), o.getTimes(), result, System.currentTimeMillis()-startTime);
                    executeSuccess(params.toJSONString(), resultJson.toJSONString());

                } catch (Exception e) {
                    logger.error("===SendFlashChatMsgTaskExecuteFailed, fromUserCode:{}, toUserCode:{},times:{}", o.getUserCode(), o.getUserCodeWlm(), o.getTimes(), e);
                    executeFailed(params.toJSONString(), resultJson == null ? "" : resultJson.toJSONString());
                }
            }
        }
    }

    /**
     * 发送失败的任务需要补发
     */
    @Scheduled(fixedDelay = 1000 * 5)
    public void tryRun() {
       List<UserSendMsgDetailEntity> failedTask = userSendMsgDetailDao.listFailedTask();
       if (CollectionUtils.isEmpty(failedTask)) {
           return;
       }
       for (UserSendMsgDetailEntity task : failedTask) {
           // 执行次+1
           task.setExecuteTimes(task.getExecuteTimes()+1);

           final HashMap<String, String> header = Maps.newHashMap();
           header.put("accept", "application/json");
           header.put("content-type", "application/json");
           final String result = HttpUtil.postPageBody(sendFlashchatUrl, header, task.getRequest());
           JSONObject resultJson = JSONObject.parseObject(result);
           final int code = resultJson.getIntValue("code");
           if (code != 0) {
               task.setResponse(resultJson.toJSONString());
               userSendMsgDetailDao.updateByPrimaryKey(task);
               continue;
           }


           task.setExecuteTimes(task.getExecuteTimes()+1);
           task.setResponse(resultJson.toJSONString());
           task.setStatus(1);
           userSendMsgDetailDao.updateByPrimaryKey(task);
       }
    }

    private void executeFailed(String request, String response) {
        try {
            UserSendMsgDetailEntity entity = new UserSendMsgDetailEntity();
            entity.setStatus(2);
            entity.setRequest(request);
            entity.setResponse(response);
            entity.setTaskName(taskName);
            entity.setExecuteTimes(1);
            userSendMsgDetailDao.insert(entity);
        } catch (Exception e) {
            logger.error("SendFlashChatMsgTask-AddTaskFailed", e);
        }
    }


    private void executeSuccess(String request, String response) {
        try {
            UserSendMsgDetailEntity entity = new UserSendMsgDetailEntity();
            entity.setStatus(1);
            entity.setRequest(request);
            entity.setResponse(response);
            entity.setTaskName(taskName);
            entity.setExecuteTimes(1);
            userSendMsgDetailDao.insert(entity);
        } catch (Exception e) {
            logger.error("SendFlashChatMsgTask-AddTaskFailed", e);
        }
    }



    private void addGreetingSendLog(UserWlmDBO o, String sendMsgs) {
        UserGreetingSendLogEntity sendEntity = new UserGreetingSendLogEntity();
        sendEntity.setFromUserCode(o.getUserCode());
        sendEntity.setToUserCode(o.getUserCodeWlm());
        sendEntity.setContent(sendMsgs);
        userGreetingSendLogDao.insert(sendEntity);
    }

    private void pushMessage(String fromUseCode, String toUserCode, String target) {
        pushEventBus.post(buildEvent(fromUseCode, toUserCode, target));
    }

    private Event buildEvent(String fromUseCode, String toUserCode, String target) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("type", ParameterTypeEnum.PUSH_MODEL_ONLINE.getId());
        params.put("target", target);
        params.put("online", OnlineStatus.ONLINE_STATUS.getType());
        return Event.builder().eventActionEnum(ActionEnum.PUSH_MSG).fromUserCode(fromUseCode).toUserCode(toUserCode).app(AppEnum.MEBOO).content(JSONObject.toJSONString(params)).build();
    }

    private String getCommonGreeting() {
        String commonGreeting = null;
        List<String> oneUserGreetingCommonContent = userGreetingCommonContentDao.getGreetingContent("125", 1, AppCodeEnum.MEBOO.getAppCode());
        List<String> twoUserGreetingCommonContent = userGreetingCommonContentDao.getGreetingContent("126", 1, AppCodeEnum.MEBOO.getAppCode());
        if (oneUserGreetingCommonContent.isEmpty() || twoUserGreetingCommonContent.isEmpty()) {
            return null;
        }
        oneUserGreetingCommonContent.add(twoUserGreetingCommonContent.get(0));
        commonGreeting = String.join("|", oneUserGreetingCommonContent);
        return commonGreeting;
    }

    private String getUserGreetingContentEntities(String userCode, String commonContentEntities) {
        final List<UserGreetingContentEntity> userGreetingContentEntities = userGreetingContentDao.queryGreetingByModelUserCode(userCode);
        if (CollectionUtils.isNotEmpty(userGreetingContentEntities)) {
            final List<UserGreetingContentEntity> approvalGreetings = userGreetingContentEntities.parallelStream().filter(o -> Objects.nonNull(o.getStatus()) && o.getStatus() == 1).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(approvalGreetings)) {
                Collections.shuffle(approvalGreetings);
                return approvalGreetings.get(0).getGreetingContent();
            }
        }
        if (StringUtils.isNotEmpty(commonContentEntities)) {
            return commonContentEntities;
        }
        return Strings.EMPTY;
    }
}
